//
//  SmartGridViewcontroller.swift
//  PhotoBrowse
//
//  Created by baiju on 2023/11/30.
//  Copyright © 2023 Apple. All rights reserved.
//


import UIKit
import Photos
import PhotosUI


class SmartGridViewController: UICollectionViewController, UIGestureRecognizerDelegate {
    
    let TMP_SELECTED_LPHOTOS_LABEL = "已选中%d项"
    
    var fetchResult: PHFetchResult<PHAsset>!
    var allPhotos: [String: [PHAsset]] = [:]
    var allPhotosIndex:[String: Int] = [:]
    // 当前选中的照片
    var selectedPhotos = Set<IndexPath>()
    // 当前选中的照片
    var curSelectedPhotos = Set<IndexPath>()
    var myPanGestureRecognizer: UIPanGestureRecognizer?
    
    // 工具栏
    let toolbarView = UIView()
    let selectedPhotosLabel = UILabel()


    fileprivate let imageManager = PHCachingImageManager()
    fileprivate var thumbnailSize: CGSize!
    fileprivate var previousPreheatRect = CGRect.zero
    
    @IBOutlet weak var collectionViewFlowLayout: UICollectionViewFlowLayout!

    
    override func viewDidLoad() {
        super.viewDidLoad()
        PHPhotoLibrary.shared().register(self)
        collectionView.register(SectionHeaderView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "HeaderView")
        let selectButtonItem = UIBarButtonItem(title: "选择", style: .plain, target: self, action: #selector(self.selectItem ))
        navigationItem.rightBarButtonItem = selectButtonItem
        collectionView.register(FooterView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "FooterView")

        // 配置工具栏视图
        toolbarView.backgroundColor = .lightGray // 设置背景色
        toolbarView.isHidden = true
        view.addSubview(toolbarView)

        // 设置工具栏视图的约束
        toolbarView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            toolbarView.heightAnchor.constraint(equalToConstant: 50), // 高度
            toolbarView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            toolbarView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            toolbarView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) // 定位在底部
        ])
        
        // 创建两个按钮
        let shareButton = UIButton(type: .system)
        let saveButton = UIButton(type: .system)
        shareButton.setTitle("分享", for: .normal)
        shareButton.addTarget(self, action: #selector(self.shareItem), for: .touchUpInside)
        saveButton.setTitle("保存", for: .normal)
        saveButton.addTarget(self, action: #selector(self.saveItem), for: .touchUpInside)
        
        // 创建堆栈视图并添加按钮
        let stackView = UIStackView(arrangedSubviews: [shareButton, selectedPhotosLabel, saveButton])
        stackView.axis = .horizontal
        stackView.distribution = .fillEqually
        stackView.spacing = 10
        toolbarView.addSubview(stackView)

        // 设置堆栈视图的约束
        stackView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            stackView.topAnchor.constraint(equalTo: toolbarView.topAnchor),
            stackView.bottomAnchor.constraint(equalTo: toolbarView.bottomAnchor),
            stackView.leadingAnchor.constraint(equalTo: toolbarView.leadingAnchor),
            stackView.trailingAnchor.constraint(equalTo: toolbarView.trailingAnchor)
        ])

        // Reaching this point without a segue means that this AssetGridViewController
        // became visible at app launch. As such, match the behavior of the segue from
        // the default "All Photos" view.
        if fetchResult == nil {
            let allPhotosOptions = PHFetchOptions()
            allPhotosOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
            allPhotosOptions.fetchLimit = 1000
            fetchResult = PHAsset.fetchAssets(with: allPhotosOptions)
        }
        
        fetchResult.enumerateObjects { (asset, index, _) in
            if(self.hasAlbumsForAsset(asset)) {
                return
            }
            guard let creationDate = asset.creationDate else { return }
            let date = self.formatDate(creationDate)

            // 直接尝试获取数组，如果不存在则创建一个新数组
            var list = self.allPhotos[date] ?? []
            // 向数组追加新元素
            list.append(asset)
            // 同时更新数组和索引
            self.allPhotos[date] = list
            self.allPhotosIndex[asset.localIdentifier] = list.count - 1

        }
        
    }
    
    deinit {
        PHPhotoLibrary.shared().unregisterChangeObserver(self)
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        // Determine the size of the thumbnails to request from the PHCachingImageManager.
        let scale = UIScreen.main.scale
        let cellSize = collectionViewFlowLayout.itemSize
        thumbnailSize = CGSize(width: cellSize.width * scale, height: cellSize.height * scale)
        navigationController?.isNavigationBarHidden = false
    }
    
    
    // 返回集合视图中部分的数量
    override func numberOfSections(in collectionView: UICollectionView) -> Int {
        return allPhotos.count
    }
    
    override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
//        if kind == UICollectionView.elementKindSectionFooter {
//            let footer = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "FooterView", for: indexPath) as! FooterView
//            // 在这里配置 footer 视图，例如添加动作处理等
//            return footer
//        }
        guard let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "HeaderView", for: indexPath) as? SectionHeaderView else {
            fatalError("Invalid view type")
        }
        
        let date = Array(allPhotos.keys).sorted()[indexPath.section]
        headerView.titleLabel.text = date
        
        return headerView
    }
    
    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        let date = Array(allPhotos.keys).sorted()[section]
        return allPhotos[date]?.count ?? 0
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
//        let cell = tableView.dequeueReusableCell(withIdentifier: "PhotoCell", for: indexPath)
        // Dequeue a GridViewCell.
        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "GridViewCell", for: indexPath) as? GridViewCell
            else { fatalError("Unexpected cell in collection view") }

        
        let date = Array(allPhotos.keys).sorted()[indexPath.section]
        if let assets = allPhotos[date] {
            let asset = assets[indexPath.row]
            
            // Add a badge to the cell if the PHAsset represents a Live Photo.
            if asset.mediaSubtypes.contains(.photoLive) {
                cell.livePhotoBadgeImage = PHLivePhotoView.livePhotoBadgeImage(options: .overContent)
            }
            
            // Request an image for the asset from the PHCachingImageManager.
            cell.representedAssetIdentifier = asset.localIdentifier
            imageManager.requestImage(for: asset, targetSize: thumbnailSize, contentMode: .aspectFill, options: nil, resultHandler: { image, _ in
                // UIKit may have recycled this cell by the handler's activation time.
                // Set the cell's thumbnail image only if it's still showing the same asset.
                if cell.representedAssetIdentifier == asset.localIdentifier {
                    cell.thumbnailImage = image
                }
            })
        }
        
        return cell
    }
    
    @objc func selectItem(_ sender: UIBarButtonItem) {
        collectionView.allowsMultipleSelection = !collectionView.allowsMultipleSelection
        if let currentTitle = sender.title{
            let newTitle = (currentTitle == "取消选择") ? "选择" : "取消选择"
            sender.title = newTitle
        }
        if collectionView.allowsMultipleSelection == true {
            self.myPanGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture))
            self.myPanGestureRecognizer!.delegate = self
            self.collectionView.addGestureRecognizer(myPanGestureRecognizer!)
            self.toolbarView.isHidden = false
        } else {
            self.collectionView.removeGestureRecognizer(self.myPanGestureRecognizer!)
            for indexPath in self.selectedPhotos {
                if let cell = collectionView.cellForItem(at: indexPath) as? GridViewCell {
                    cell.isSelected = false
                }
            }
            self.selectedPhotos.removeAll()
            self.toolbarView.isHidden = true
        }
        selectedPhotosLabel.text = String(format: TMP_SELECTED_LPHOTOS_LABEL, self.selectedPhotos.count)
    }
    
    @objc func shareItem(_ sender: UIButton) {
        // 创建并配置 UIAlertController
        let alert = UIAlertController(title: "提示", message: "分享成功", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "确认", style: .default, handler: nil))

        // 显示弹框
        present(alert, animated: true, completion: nil)
    }
    
    @objc func saveItem(_ sender: UIButton) {
        let alert = UIAlertController(title: "提示", message: "保存成功", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "确认", style: .default, handler: nil))

        // 显示弹框
        present(alert, animated: true, completion: nil)
    }
    
    // UIGestureRecognizerDelegate 方法
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        let point = gestureRecognizer.location(in: self.collectionView)
        if let indexPath = self.collectionView.indexPathForItem(at: point),
           let _ = self.collectionView.cellForItem(at: indexPath) as? GridViewCell {
            // 如果手势起点在 gridCell 内，不允许同时识别
            return false
        }
        return true
    }
    
    @objc func handlePanGesture(gesture: UIPanGestureRecognizer) {
        let location = gesture.location(in: collectionView)
        guard let indexPath = collectionView.indexPathForItem(at: location) else { return }

        switch gesture.state {
        case .began:
            self.curSelectedPhotos.removeAll()
        case .changed:
            if self.curSelectedPhotos.contains(indexPath) {
                break;
            }
            // 这里添加逻辑来处理选中状态的变化
            // 例如，可以切换 indexPath 对应的单元格的选中状态
            if let cell = collectionView.cellForItem(at: indexPath) as? GridViewCell {
                cell.isSelected = !cell.isSelected
                if cell.isSelected {
                    self.selectedPhotos.insert(indexPath)
                } else {
                    self.selectedPhotos.remove(indexPath)
                }
            }
            self.curSelectedPhotos.insert(indexPath)
        default:
            break
        }
        selectedPhotosLabel.text = String(format: TMP_SELECTED_LPHOTOS_LABEL, self.selectedPhotos.count)
    }
    
    override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        if selectedPhotos.contains(indexPath) {
            selectedPhotos.remove(indexPath)
        } else {
            selectedPhotos.insert(indexPath)
        }
        collectionView.reloadItems(at: [indexPath])
        
    }
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        guard let destination = segue.destination as? AssetViewController else { fatalError("Unexpected view controller for segue") }
        guard let collectionViewCell = sender as? UICollectionViewCell else { fatalError("Unexpected sender for segue") }
        
        let indexPath = collectionView.indexPath(for: collectionViewCell)!
        let date = Array(allPhotos.keys).sorted()[indexPath.section]
        guard let list = self.allPhotos[date] else { return }
        destination.asset = list[indexPath.item]
    }
    
    func formatDate(_ date: Date) -> String {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd" // 或其他你想要的格式
        return dateFormatter.string(from: date)
    }
    
    func hasAlbumsForAsset(_ asset: PHAsset) -> Bool {
        let albumsContainingAsset = PHAssetCollection.fetchAssetCollectionsContaining(asset, with: .album, options: nil)
        return albumsContainingAsset.count > 0
    }
    
    func resetPhotosIndex(date: String, id: String){
        guard let list = self.allPhotos[date] else { return }
        for (index, asset) in list.enumerated() {
            self.allPhotosIndex[asset.localIdentifier] = index
        }
    }
  
}


class SectionHeaderView: UICollectionReusableView {
    static let reuseIdentifier = "HeaderView"

    let titleLabel = UILabel()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupViews()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupViews()
    }
    
    private func setupViews() {
        addSubview(titleLabel)
        titleLabel.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            titleLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 10),
            titleLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -10),
            titleLabel.topAnchor.constraint(equalTo: topAnchor),
            titleLabel.bottomAnchor.constraint(equalTo: bottomAnchor)
        ])
    }
}


// MARK: PHPhotoLibraryChangeObserver
extension SmartGridViewController: PHPhotoLibraryChangeObserver {
    func photoLibraryDidChange(_ changeInstance: PHChange) {
        
        guard let changes = changeInstance.changeDetails(for: fetchResult)
            else { return }
        
        // Change notifications may originate from a background queue.
        // As such, re-dispatch execution to the main queue before acting
        // on the change, so you can update the UI.
        DispatchQueue.main.sync {
            // Hang on to the new fetch result.
            fetchResult = changes.fetchResultAfterChanges
            // If we have incremental changes, animate them in the collection view.
            if changes.hasIncrementalChanges {
                guard let collectionView = self.collectionView else { fatalError() }
                // Handle removals, insertions, and moves in a batch update.
                
                // We are reloading items after the batch update since `PHFetchResultChangeDetails.changedIndexes` refers to
                // items in the *after* state and not the *before* state as expected by `performBatchUpdates(_:completion:)`.
                if let changed = changes.changedIndexes, !changed.isEmpty {
                    changed.enumerated().forEach { (index, cur) in
                        let changedAsset = self.fetchResult.object(at: cur)
                        guard let creationDate: Date = changedAsset.creationDate else { return }
                        let sectionKey = self.formatDate(creationDate)

                        if self.hasAlbumsForAsset(changedAsset), let i = self.allPhotosIndex[changedAsset.localIdentifier] {
                            if (self.allPhotos[sectionKey] == nil) {
                                return
                            }
                            self.allPhotos[sectionKey]?.remove(at: i)
                            // TODO update index
                            guard let s = Array(allPhotos.keys).sorted().firstIndex(of: sectionKey) else { return }
                            collectionView.deleteItems(at: [IndexPath(item: i, section: s)])
                            print("delete items \(i), \(s), \(sectionKey)")
                            self.resetPhotosIndex(date: sectionKey, id: changedAsset.localIdentifier)
                        }
                    }
                }
            } else {
                // Reload the collection view if incremental changes are not available.
                collectionView.reloadData()
            }
        }
    }
}

class FooterView: UICollectionReusableView {
    let shareButton = UIButton(type: .system)
    let saveButton = UIButton(type: .system)

    override init(frame: CGRect) {
        super.init(frame: frame)

        // 配置按钮
        shareButton.setTitle("分享", for: .normal)
        saveButton.setTitle("保存", for: .normal)

        // 设置布局
        let stackView = UIStackView(arrangedSubviews: [shareButton, saveButton])
        stackView.axis = .horizontal
        stackView.distribution = .fillEqually
        stackView.spacing = 10
        addSubview(stackView)
        stackView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            stackView.topAnchor.constraint(equalTo: topAnchor),
            stackView.bottomAnchor.constraint(equalTo: bottomAnchor),
            stackView.leadingAnchor.constraint(equalTo: leadingAnchor),
            stackView.trailingAnchor.constraint(equalTo: trailingAnchor)
        ])
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
